The below is taken from: http://weblogs.asp.net/mdavey/pages/79456.aspx I came across it a few years ago and found it useful based on what i was doing at the time, I just found it again in my browser favourites so thought i would post it for the sake of completeness….
Tibco RV is often used in investment banks to send market data. Its therefore going to be a requirement for any front-office trading application running on Linux and Mono to subscribe to Tibco RV subjects. What follows is a simple example of the code required to do this – effectively a Mono language binding for Tibco RV. This code was written on RedHat 9.0, with Mono 0.30, and Tibco 7.2.
First we need a C++ library (.so) which uses the Tibco RV C++ API to setup a simple subscription. Callback’s from C++ to C# (unmanaged to managed) are handled by C++ function pointers and normal C# delegates. The C++ “Start” function below will be called by C#, passing a C# delegate, which the C++ will callback on when a message is received on the Tibco RV subject.
#include
#include
#include
#include
#include
#include “tibrv/tibrvcpp.h”
/*********************************************************************/
/* Transport parameters */
/*********************************************************************/
char* serviceStr = NULL;
char* networkStr = NULL;
char* daemonStr = “tcp::7500”;
typedef void (*stringFunction)(char*);
stringFunction stringFunctionPtr;
/*********************************************************************/
/* Message callback class */
/*********************************************************************/
class MsgCallback : public TibrvMsgCallback
{
public:
void onMsg(TibrvListener* listener, TibrvMsg& msg)
{
const char* sendSubject = NULL;
const char* replySubject = NULL;
const char* msgString = NULL;
// Get the subject name to which this message was sent
msg.getSendSubject(sendSubject);
// If there was a reply subject, get it
msg.getReplySubject(replySubject);
// Convert the incoming message to a string
msg.convertToString(msgString);
if (replySubject != NULL)
printf(“subject=%s, reply=%s, message=%s\n”, sendSubject, replySubject, msgString);
else
printf(“subject=%s, message=%s\n”, sendSubject, msgString);
printf(“About to do callback to C#\n”);
(*stringFunctionPtr)((char*)msgString);
fflush(stdout);
}
};
extern “C” void Start(stringFunction f)
{
stringFunctionPtr = f;
TibrvStatus status;
// open Tibrv
status = Tibrv::open();
if (status != TIBRV_OK)
{
fprintf(stderr,”Error: could not open TIB/RV, status=%d, text=%s\n”, (int)status,status.getText());
exit(-1);
}
// Create network transport
TibrvNetTransport transport;
status = transport.create(serviceStr,networkStr,daemonStr);
if (status != TIBRV_OK)
{
fprintf(stderr,”Error: could not create transport, status=%d, text=%s\n”, (int)status,status.getText());
Tibrv::close();
exit(-1);
}
transport.setDescription(“SomeSubject”);
TibrvListener* listener = new TibrvListener();
status=listener->create(Tibrv::defaultQueue(),new MsgCallback(),&transport,”SomeSubject”);
if (status != TIBRV_OK)
{
fprintf(stderr,”Error: could not create listener on %s, status=%d, text=%s\n”, “SomeSubject”,(int)status,status.getText());
Tibrv::close();
exit(-1);
}
printf(“Listening on: %s\n”,”SomeSubject”);
fflush(stdout);
// dispatch Tibrv events
while((status=Tibrv::defaultQueue()->dispatch()) == TIBRV_OK);
// if everything is Ok we’ll never get here
fprintf(stderr,”Error: dispatch failed, status=%d, text=%s\n”, (int)status,status.getText());
Tibrv::close();
exit(-1);
}
We use the DllImport .NET attribute to tell C# where the C++ “Start” method should be located. The TibCallback delegate must match the C++ function pointer stringFunction from an argument perspective.
using System;
using System.Threading;
using System.Runtime.InteropServices;
namespace Test
{
public delegate void TibCallback(string s);
public class Class1
{
[DllImport(“”, CharSet=CharSet.Ansi)]
public static extern void Start(Delegate d);
private Thread tibThread;
static void Main(string[] args)
{
new Class1().Run();
}
public void Run()
{
tibThread = new Thread(new ThreadStart(StartTib));
tibThread.IsBackground = true;
tibThread.Name = “TibThread”;
tibThread.Start();
Console.ReadLine();
}
private void StartTib()
{
Start(new TibCallback(this.TibMsg));
}
public void TibMsg(string s) {
Console.WriteLine(“TibMsg called”);
Console.WriteLine(s);
}
}
}